package com.itcast.peft.service;

import java.util.concurrent.CompletableFuture;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.itcast.peft.entity.Answer;
import com.itcast.peft.entity.report.HealthReportVo;
import com.itcast.peft.mapper.AnswerMapper;
import com.itcast.peft.util.AsyncWrapper;
import com.itcast.peft.util.ExceptionWrapper;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class HealthAccuracyEvaluateService {
    
    private ObjectMapper objectMapper = new ObjectMapper();
    /**
     * 数据量较大，起并发
     */
    @Autowired
    private AsyncWrapper asyncWrapper;

    @Autowired
    private AnswerMapper answerMapper;
    
    @Async
    public void accuracyEvaluate(String refGroup, String ansGroup) {
        var refMap = answerMapper.questionId2dataByGroup(refGroup);
        var ansMap = answerMapper.questionId2dataByGroup(ansGroup);

        var evalList = ansMap
                .keySet().stream().limit(100).map(qid -> CompletableFuture
                        .runAsync(() -> accEval(refMap.get(qid), ansMap.get(qid)), asyncWrapper.getExecutor()))
                .toList();
        evalList.forEach(ExceptionWrapper.<CompletableFuture<Void>, Void>wrapToRTE(CompletableFuture::get)::apply);
        log.info("accuracy evaluation[{}] task completed:{}", refGroup, ansGroup);
    }

    private void accEval(Answer ref, Answer ans) {
        var refReport = fromJson(ref.getAnswer());
        var ansReport = fromJson(ans.getAnswer());
        if(refReport != null && ansReport != null) {
            // 评分标准：
            int score = ansReport.accuracyScore(refReport);
            ans.setEvalScore(score);
            ans.setEvalResult("精确计算");
            var res = answerMapper.updateById(ans);
            log.info("update acc eval score:{}", res);
        } else {
            log.warn("null struct resport:{},{}",ref.getAnswer(), ans.getAnswer());
        }
    }
    
    public HealthReportVo fromJson(String json) {
        try {
            return objectMapper.readValue(json, HealthReportVo.class);
        } catch (Exception e) {
            log.error("json parse error", e);
            return null;
        }
    }

}
